package play.cnblog.cli.service.impl;

import java.nio.file.Files;
import java.nio.file.Paths;
import com.vladsch.flexmark.ast.Image;
import com.vladsch.flexmark.formatter.Formatter;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.ast.NodeVisitor;
import com.vladsch.flexmark.util.ast.VisitHandler;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import play.cnblog.cli.model.Blog;
import play.cnblog.cli.model.Media;
import play.cnblog.cli.rpc.CnblogRpc;
import play.cnblog.cli.service.CnblogMediaService;

public class CnblogMediaServiceImpl implements CnblogMediaService {

    /**
     * 本地协议
     */
    private final String protocol;
    /**
     * 本地图片库地址
     */
    private final String mediaLibDir;
    /**
     * markdown 处理
     */
    private final NodeVisitor visitor;
    /**
     * cnblog rpc
     */
    private final CnblogRpc cnblogRpc;

    public CnblogMediaServiceImpl(CnblogRpc cnblogRpc, String protocol,
        String mediaLibDir) {
        this.cnblogRpc = cnblogRpc;
        this.protocol = protocol;
        this.mediaLibDir = mediaLibDir;
        this.visitor = new NodeVisitor
            (new VisitHandler<>(Image.class, this::visitor));
    }

    @Override
    public void uploadMedia(Blog blog) {
        String content = blog.getDescription();
        Parser parser = Parser.builder().build();
        Node node = parser.parse(content);
        visitor.visit(node);

        Formatter formatter = Formatter.builder().build();
        String formatContent = formatter.render(node);
        blog.setDescription(formatContent);
    }

    /*
     * 1、本地协议
     * 2、获取图片地址
     * 3、cnblog 上传素材
     * 4、本地图片和cnblog图片保存数据库映射
     */
    private void visitor(Image image) {
        String localUrl = image.getUrl().unescape();
        if (localUrl.startsWith(this.protocol)) {
            String cnblogMediaUrl = upload(localUrl);
            image.setUrlChars(BasedSequence.of(cnblogMediaUrl));
        }
    }

    private String upload(String localUrl) {
        String fileName = localUrl.substring(this.protocol.length());
        String fileType = fileType(fileName);
        String filePath = this.mediaLibDir + fileName;

        try {
            byte[] bs = Files.readAllBytes(Paths.get(filePath));
            Media media = new Media();
            media.setBits(bs);
            media.setName(fileName);
            media.setType(fileType);
            return cnblogRpc.uploadMedia(media);
        }
        catch (Exception ex) {
            throw new RuntimeException("upload media fail.", ex);
        }
    }

    private String fileType(String fileName) {
        String[] splits = fileName.split("\\.");
        String type = splits[splits.length - 1];
        return "image/" + type;
    }
}
